import axios, { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse } from 'axios';
import msg from '@/utils/messageTool';
import { debounce } from 'lodash';

// 防抖 key 映射
interface DebounceMap {
  [key: string]: (...args: any[]) => void;
}
const debounceMap: DebounceMap = {};

// 创建 axios 实例
const instance: AxiosInstance = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL || '',
  timeout: 10000,
  headers: { 'Content-Type': 'application/json' },
});

// 请求拦截器
instance.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    // const token = localStorage.getItem('app_token');
    // if (token && config.headers) config.headers['Authorization'] = `Bearer ${token}`;
    return config;
  },
  (error) => {
    msg.error({ content: '请求发送失败' });
    return Promise.reject(error);
  }
);

// 响应拦截器
instance.interceptors.response.use(
  (response: AxiosResponse) => {
    const data = response.data;
    // 自定义 code 判断，可根据实际项目调整
    if (data.code && data.code !== 200) {
      msg.error({ content: data.message || '请求失败' });
      return Promise.reject(data);
    }
    return data;
  },
  (error) => {
    if (error.response) {
      const status = error.response.status;
      switch (status) {
        case 401:
          msg.error({ content: '未授权，请登录' });
          break;
        case 403:
          msg.error({ content: '没有权限' });
          break;
        case 404:
          msg.error({ content: '请求接口不存在' });
          break;
        case 500:
          msg.error({ content: '服务器错误' });
          break;
        default:
          msg.error({ content: error.message || '请求错误' });
      }
    } else {
      msg.error({ content: '网络异常，请检查网络' });
    }
    return Promise.reject(error);
  }
);

// 防抖 + Loading + 自动提示封装
function requestWithDebounce<T>(
  fn: () => Promise<T>,
  key: string,
  options?: { loadingMessage?: string; successMessage?: string; errorMessage?: string; debounceTime?: number }
): Promise<T> {
  const { loadingMessage, successMessage, errorMessage, debounceTime = 500 } = options || {};
  return new Promise((resolve, reject) => {
    if (!debounceMap[key]) {
      debounceMap[key] = debounce(
        (callback: (err?: any, res?: T) => void) => {
          // 显示 loading
          const closeLoading = loadingMessage ? msg.loading({ content: loadingMessage }) : () => {};
          fn()
            .then((res) => {
              closeLoading();
              if (successMessage) msg.success({ content: successMessage });
              callback(undefined, res);
            })
            .catch((err) => {
              closeLoading();
              if (errorMessage) msg.error({ content: errorMessage });
              callback(err);
            });
        },
        debounceTime,
        { leading: true, trailing: false }
      );
    }

    debounceMap[key]((err?: any, res?: T) => {
      if (err) reject(err);
      else resolve(res as T);
    });
  });
}

// GET 请求
export function get<T = any>(
  url: string,
  params?: object,
  config?: InternalAxiosRequestConfig,
  options?: { debounceKey?: string; loadingMessage?: string; successMessage?: string; errorMessage?: string; debounceTime?: number }
): Promise<T> {
  const requestFn = () => instance.get(url, { params, ...config }).then(res => res.data);
  if (options?.debounceKey) return requestWithDebounce(requestFn, options.debounceKey, options);
  return requestFn();
}

// POST 请求
export function post<T = any>(
  url: string,
  data?: object,
  config?: InternalAxiosRequestConfig,
  options?: { debounceKey?: string; loadingMessage?: string; successMessage?: string; errorMessage?: string; debounceTime?: number }
): Promise<T> {
  const requestFn = () => instance.post(url, data, config).then(res => res.data);
  if (options?.debounceKey) return requestWithDebounce(requestFn, options.debounceKey, options);
  return requestFn();
}

// PUT 请求
export function put<T = any>(
  url: string,
  data?: object,
  config?: InternalAxiosRequestConfig,
  options?: { debounceKey?: string; loadingMessage?: string; successMessage?: string; errorMessage?: string; debounceTime?: number }
): Promise<T> {
  const requestFn = () => instance.put(url, data, config).then(res => res.data);
  if (options?.debounceKey) return requestWithDebounce(requestFn, options.debounceKey, options);
  return requestFn();
}

// DELETE 请求
export function del<T = any>(
  url: string,
  data?: object,
  config?: InternalAxiosRequestConfig,
  options?: { debounceKey?: string; loadingMessage?: string; successMessage?: string; errorMessage?: string; debounceTime?: number }
): Promise<T> {
  const requestFn = () => instance.delete(url, { data, ...config }).then(res => res.data);
  if (options?.debounceKey) return requestWithDebounce(requestFn, options.debounceKey, options);
  return requestFn();
}

export default instance;
